package masterclient;

import Protocol.ClientObject;
import Protocol.ComProtocol;
import Protocol.ReturnObject;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.util.ArrayList;
import javax.swing.JTable;
import sun.security.provider.MD5;

/**
 * In deze klasse wordt de authenticatie afgehandeld : het in- en uitloggen, encryptie van wachtwoorden, ophalen van de beschikbare query's
 * en het verwerken van geselecteerde query's
 * @author Michael Stevens 
 * @since 17-05-2012
 */
public class Authentication {
    
    private Masterclient mc;
    private ComProtocol cp;
    private String[] query;
    private boolean qSelected = false, loggedIn = false;
    private String userName, passWord;
    
    
    public Authentication(Masterclient mc){
        this.mc = mc;
    }  
    
    /**
    * Methode om een string om te zetten naar een md5 hash. Dit voor wachtwoord encryptie
    * @return Wachtwoord als MD5 hash
    * @author Michael Stevens
    * @since 19-05-2011
    */
    public String encrypt(String s){
        String encrypted = "";
        try{            
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] array = md.digest(s.getBytes("UTF-8"));
            
            StringBuffer sb = new StringBuffer();            
            for (int i = 0; i < array.length; ++i) {
                sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3));
                //sb.append(Integer.toHexString(0xFF & array[i]));
            }        
            encrypted = sb.toString();            
        }catch(Exception e){
            System.out.println(e.getMessage());
        }
        return encrypted;
    }
    
    /**
    * Methode om in te loggen. Hier wordt de encrypt methode aangeroepen op het password.
    * Als gegevens correct zijn worden tabbladen in de GUI bruikbaar.
    * @author Michael Stevens
    * @since 17-05-2011
    */
    public void logIn(String userName, String passWord){
        cp = new ComProtocol("localhost", 5555);
        ClientObject o = new ClientObject(userName, encrypt(passWord), cp.getInloggen(), "");
        cp.send(o);
        ReturnObject ro = (ReturnObject) cp.recieve(); 
        cp.close();
            if(ro != null){
                if(ro.getMessage().equals("ok")){
                    loggedIn = true;
                    this.userName = userName;
                    this.passWord = encrypt(passWord);
                    mc.getGUI().clearFields();
                    getQuerys();
                    mc.getGUI().enableAllTabs(true);
                    mc.getGUI().enableLoginTab(false);
                    mc.getGUI().getTabbedPane().setSelectedIndex(1);
                                                            
                }else{
                    mc.getGUI().showMessageD("Foute login gegevens");  
                }
            }else{
                mc.getGUI().showMessageD("Geen verbinding met de server");                
            }
    }
    
    /**
    * Methode om de gebruiker uit te loggen. Wanneer de gebruiker uitgelogd is 
    * worden de tabbladen binnen de GUI onbruikbaar
    * @author Michael Stevens
    * @since 18-05-2011
    */
    public void logOut(){
        cp = new ComProtocol("localhost", 5555);
        ClientObject o = new ClientObject(userName, passWord, cp.getUitloggen(), "");
        cp.send(o);
        ReturnObject ro = (ReturnObject) cp.recieve(); 
        cp.close();
        if(ro == null){            
        }else{    
            if(ro.getMessage().equals("ok")){
                loggedIn = false;
                passWord = "";
                userName = "";
                
                mc.getGUI().enableAllTabs(true);
                mc.getGUI().getTabbedPane().setSelectedIndex(0);
            }else{                
            }
        }
    }
    
    /**
    * Methode om query uit te voeren. 
    * @return ReturnObject met query results.
    * @author Michael Stevens
    * @since 03-05-2011
    */
    public ReturnObject excecuteQuery(int index){
        cp = new ComProtocol("localhost", 5555);
        ClientObject o = new ClientObject(userName, passWord, cp.getSelectQuery(), query[index]);
        cp.send(o);
        ReturnObject ro = (ReturnObject) cp.recieve(); 
        cp.close();
        
        return ro;
    }
    
    /**
    * Methode om de vooringestelde query's op te halen. De combolist wordt hierna gemaakt.   
    * @author Michael Stevens
    * @since 19-05-2011
    */
    public void getQuerys(){
        cp = new ComProtocol("localhost", 5555);
        ClientObject o = new ClientObject("system", "54b53072540eeeb8f8e9343e71f28176", cp.getAuthSelectQuery(), "SELECT [query], [description] FROM Query WHERE isActive = 1");
        cp.send(o);
        ReturnObject ro = (ReturnObject) cp.recieve(); 
        cp.close();        
            
    }
    
    /**
    * Hier wordt het binnenkomende returnobject uitgelezen en worden de 
    * omschrijving van de query en de query zelf apart in en array gezet.
    * @return de array string met omschrijving
    * @author Michael Stevens
    * @since 17-05-2012
    */
    public String[] verwerkReturnObject(ReturnObject ro){       
        int counter = 0;
        String[] desc = new String[ro.getRijen().size()];
        query = new String[ro.getRijen().size()];
        for(ArrayList a:ro.getRijen()){
            desc[counter] = a.get(1).toString();
            query[counter] = a.get(0).toString();
            counter++;
        }
        return desc;
    }
    
    public JTable test(ReturnObject ro){
        //Array voor kolommen aanmaken
        //Array index grote kan worden opgehaald door .size() van de arraylist
        // met de methode toArray kan de arraylist omgezet worden naar een array
        String[] cols = new String[ro.getKolommen().size()];        
        ro.getKolommen().toArray(cols);

        
        // 2d Array voor de rijen
        // rij index is weer op te halen met .size() uit de omkoepelende arraylist
        // kolom index wordt met een for loop opgehaald door het aantal objecten in de arraylist die in de arraylist zit te tellen
        // en dit vervolgens te delen door het aantal rijen zodat je aantal kolommen per rij krijgt : 2rijen 2kolommen telt 4kolommen totaal / 2 = 2
        int i = 0;
        for(ArrayList a:ro.getRijen()){
            for(Object o:a){
                i++;
            }
        }
        i = i / ro.getRijen().size();
        String[][] data = new String[ro.getRijen().size()][i];
        
        
        // De data wegschrijven naar het 2d array
        // 2 tellers 1 voor de omkoepelende arraylist en 1 voor die daarin zit
        // door een for loop in een for loop te plaatsen kunnen we bij de kolom data komen
        // begint bij eerste rij, dan naar 2e for loop schrijft daar de data weg naar 2d array 
        //en gaat door tot alle objecten binnen die rij doorlopen zijn
        // reset dan de teller voor binnenste loop en +1 voor buitenste
        // index is nu [1][0]
        // bij een [2][2] array als binnenste teller niet gereset zou worden zaten we op index [1][2] en die bestaat niet
        int k = 0;
        int m = 0;
        for(ArrayList a:ro.getRijen()){
            
            for(Object o:a){
                data[k][m] = o.toString();
                m++;
            }
            m = 0;
            k++;
        }
        
        //maak tabel aan met de omgezette arrays
        JTable tabel = new JTable(data, cols);
        tabel.setEnabled(false);
        //en stuur deze terug
        return tabel;
        
    }

    /**
     * @return the query
     */
    public String[] getQuery() {
        return query;
    }

    /**
     * @return the loggedIn
     */
    public boolean isLoggedIn() {
        return loggedIn;
    }
}
